
package com.zjff.myshop.front.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.zjff.myshop.entity.Address;
import com.zjff.myshop.entity.Goods;
import com.zjff.myshop.entity.Order;
import com.zjff.myshop.entity.OrderItem;
import com.zjff.myshop.exception.BusinessException;
import com.zjff.myshop.front.pojo.vo.StockCountVO;
import com.zjff.myshop.front.pojo.form.OrderInsertForm;
import com.zjff.myshop.front.pojo.form.OrderItemInsertForm;
import com.zjff.myshop.front.pojo.vo.OrderDetailVO;
import com.zjff.myshop.front.pojo.vo.OrderItemVO;
import com.zjff.myshop.front.pojo.vo.OrderVO;
import com.zjff.myshop.front.service.AddressService;
import com.zjff.myshop.front.service.GoodsService;
import com.zjff.myshop.front.service.OrderService;
import com.zjff.myshop.mapper.OrderItemMapper;
import com.zjff.myshop.mapper.OrderMapper;
import com.zjff.myshop.util.BeanUtils;
import com.zjff.myshop.util.PageList;
import com.zjff.myshop.util.PageQuery;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class OrderServiceImpl implements OrderService {

    @Resource
    private OrderMapper orderMapper;
    @Resource
    private OrderItemMapper orderItemMapper;
    @Resource
    private GoodsService goodsService;
    @Resource
    private AddressService addressService;

    /**
     * 增加订单（从购物商品创建）
     */
    @Override
    @Transactional
    public Integer insert(OrderInsertForm form) {
        Integer userId = StpUtil.getLoginIdAsInt();
        //检查地址，确保存在并是自己的地址
        Integer addressId = form.getAddressId();
        Address address = addressService.selectByPrimaryKey(addressId);
        if (address == null) {
            throw new BusinessException("id对应的地址不存在");
        }
        if (!userId.equals(address.getUserId())) {
            throw new BusinessException("业务数据不是你的，禁止该操作");
        }

        //检查商品项
        List<OrderItemInsertForm> orderItemList = form.getGoodsList();
        Integer[] ids = orderItemList.stream().map(OrderItemInsertForm::getGoodsId).toArray(Integer[]::new);
        List<Goods> goodsList = goodsService.selectByIds(ids);
        //检查是否包含已下架商品（0下架/1上架
        List<Goods> goodsListNotSelling = goodsList.stream().filter(item -> item.getStatus() == 0).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(goodsListNotSelling)) {
            //对象非空则表示有下架商品
            throw new BusinessException(goodsListNotSelling.get(0).getName() + "已下架，无法生成订单");
        }

        //合并相同商品，键值(goodsId)相同时，合并规则是取原来的值对象,生成选购商品的集合
        Map<Integer, Goods> goodsMap = goodsList.stream().collect(Collectors.toMap(Goods::getId, Function.identity(), (oldVal, curVal) -> oldVal));
        //检查商品库存
        for (OrderItemInsertForm item : orderItemList) {
            //订单商品不存在，直接返回错误提醒
            if (!goodsMap.containsKey(item.getGoodsId())) {
                throw new BusinessException("创建订单数据异常");
            }
            //存在数量大于库存的情况，直接返回错误提醒
            Goods goods = goodsMap.get(item.getGoodsId());
            if (item.getCount() > goods.getCount()) {
                throw new BusinessException("创建订单商品库存不足");
            }
        }

        //更新库存
        List<StockCountVO> stockCountList = BeanUtils.copyList(orderItemList, StockCountVO.class);
        //更新库存错误，则抛出异常
        if (!goodsService.updateByStockCountList(stockCountList)) {
            throw new BusinessException("更改商品库存错误");
        }

        //计算总金额
        double amount = 0.0;
        for (OrderItemInsertForm item : orderItemList) {
            amount += item.getCount() * item.getPrice().doubleValue();
        }

        //保存订单
        Order order = new Order();
        order.setUserId(userId); //订单是我的
        order.setAmount(new BigDecimal(amount));
        order.setAddressName(address.getName());
        order.setAddressTel(address.getTel());
        order.setAddressDetail(address.getCity() + address.getCounty() + address.getAddressDetail());
        //生成订单出错，抛出异常
        if (orderMapper.insert(order) <= 0) {
            throw new BusinessException("生成订单数据库错误");
        }

        //获取订单id
        //OrderMapper.xml文件insert方法中使用useGeneratedKeys 此时order.id可以生成返回
        //useGeneratedKeys="true" keyProperty="id"
        Integer orderId = order.getId();

        //生成订单项
        List<OrderItem> orderItems = new ArrayList<>();
        for (OrderItemInsertForm item : orderItemList) {
            OrderItem orderItem = new OrderItem();
            //使用BeanUtil工具类将cartItemVO中的属性复制到orderItem对象中
            BeanUtils.copyProperties(item, orderItem);

            orderItem.setOrderId(orderId);
            orderItems.add(orderItem);
        }
        //保存订单项,返回结果orderId
        return orderItemMapper.insertBatch(orderItems) > 0 ? orderId : 0;
    }

    /**
     * 更改订单信息
     */
    @Override
    @Transactional
    public Boolean update(Order order) {
        return orderMapper.update(order) > 0;
    }

    /**
     * 更改订单状态
     */
    @Override
    public Boolean updateStatus(Integer orderId, Byte status) {

        //检查订单是否存在
        Order orderTemp = orderMapper.selectByPrimaryKey(orderId);
        if (orderTemp == null) {
            throw new BusinessException("id对应的订单不存在");
        }

        //检查是否是我的订单
        Integer userId = StpUtil.getLoginIdAsInt();
        if (!userId.equals(orderTemp.getUserId())) {
            throw new BusinessException("业务数据不是你的，禁止该操作");
        }

        Order order = new Order();
        order.setId(orderId);
        order.setStatus(status);  //订单状态
        return orderMapper.update(order) > 0;
    }

    private List<OrderItemVO> selectVOByOrderId(Integer orderId) {

        List<OrderItemVO> orderItemVOList = new ArrayList<>();
        //查询订单项数据
        List<HashMap<String, Object>> mapList = orderItemMapper.selectVoByOrderId(orderId);

        //Map数组转Bean数组
        for (HashMap<String, Object> map : mapList) {
            OrderItemVO vo = BeanUtils.mapToBean(map, OrderItemVO.class);
            if (ObjectUtil.isNotNull(vo)) {
                orderItemVOList.add(vo);
            }

        }
        return orderItemVOList;
    }

    /**
     * 查询订单详情
     */
    @Override
    public OrderDetailVO selectDetailById(Integer orderId) {
        //查询订单是否存在
        Order order = orderMapper.selectByPrimaryKey(orderId);
        if (order == null) {
            throw new BusinessException("id对应的订单不存在");
        }

        OrderDetailVO orderDetailVO = new OrderDetailVO();
        BeanUtils.copyProperties(order, orderDetailVO);

        List<OrderItemVO> orderItemVOList = this.selectVOByOrderId(orderId);
        orderDetailVO.setOrderItemList(orderItemVOList);
        return orderDetailVO;
    }

    /**
     * 查询订单分页列
     */
    @Override
    public PageList<OrderVO> selectPage(PageQuery pageQuery) {
        //pageQueryUtil有 page 、 limit 、status
        PageHelper.startPage(pageQuery.getPage(), pageQuery.getLimit());
        List<Order> orderList = orderMapper.selectPage(pageQuery);
        int total = (int) new PageInfo<>(orderList).getTotal();

        List<OrderVO> orderVOList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(orderList)) {
            //数据转换 将实体类列表转成vo列表
            orderVOList = BeanUtils.copyList(orderList, OrderVO.class);
        }
        return new PageList<>(orderVOList, total, pageQuery.getLimit(), pageQuery.getPage());
    }

    /**
     * 查询我的订单明细列表
     */
    @Override
    public List<OrderDetailVO> selectDetailVOList(Map<String, Object> map) {
        //pageQueryUtil有 page 、 limit 、status
        List<Order> orderList = orderMapper.selectPage(map);
        List<OrderDetailVO> voList = BeanUtils.copyList(orderList, OrderDetailVO.class);

        for (OrderDetailVO order : voList) {
            List<OrderItemVO> orderItemVOList = this.selectVOByOrderId(order.getId());
            order.setOrderItemList(orderItemVOList);
        }
        return voList;
    }

}
